/*
 * Copyright (c) zhg2yqq.com Corp.
 * All Rights Reserved.
 */
package com.zhg2yqq.wheels.security.handler;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import com.alibaba.fastjson2.JSON;
import com.zhg2yqq.wheels.common.response.RestResponse;
import com.zhg2yqq.wheels.common.util.ServletUtils;
import com.zhg2yqq.wheels.security.ISecurityEventHook;
import com.zhg2yqq.wheels.security.constants.SecurityResponseCode;
import com.zhg2yqq.wheels.security.multi.BadCodeException;

/**
 * @author zhg2yqq, 2022年11月28日
 * @version zhg2yqq v1.0
 */
public class LoginFailureHandler implements AuthenticationFailureHandler {
    private Logger log = LoggerFactory.getLogger(LoginFailureHandler.class);
    private ISecurityEventHook eventHook;

    public LoginFailureHandler() {
        super();
    }

    public LoginFailureHandler(ISecurityEventHook eventHook) {
        super();
        this.eventHook = eventHook;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException e)
            throws IOException {
        if (!ServletUtils.isAjaxRequest(request)) {
            return;
        }
        RestResponse<Void> result;
//        String username = UserUtil.loginUsername(request);
        if (e instanceof AccountExpiredException) {
            // 账号过期
//            log.info("[登录失败] - 用户[{}]账号过期", username);
            result = RestResponse.build(SecurityResponseCode.SECURITY_ACCOUNT_EXPIRED);

        } else if (e instanceof BadCodeException) {
            // 验证码错误
            result = RestResponse.build(SecurityResponseCode.SECURITY_CODE_ERROR);
        } else if (e instanceof BadCredentialsException) {
            // 密码错误
//            log.info("[登录失败] - 用户[{}]密码错误", username);
            result = RestResponse.build(SecurityResponseCode.SECURITY_PASSWORD_ERROR);

        } else if (e instanceof CredentialsExpiredException) {
            // 密码过期
//            log.info("[登录失败] - 用户[{}]密码过期", username);
            result = RestResponse.build(SecurityResponseCode.SECURITY_PASSWORD_EXPIRED);

        } else if (e instanceof DisabledException) {
            // 用户被禁用
//            log.info("[登录失败] - 用户[{}]被禁用", username);
            result = RestResponse.build(SecurityResponseCode.SECURITY_USER_DISABLED);

        } else if (e instanceof LockedException) {
            // 用户被锁定
//            log.info("[登录失败] - 用户[{}]被锁定", username);
            result = RestResponse.build(SecurityResponseCode.SECURITY_USER_LOCKED);

        } else if (e instanceof InternalAuthenticationServiceException) {
            log.error(((InternalAuthenticationServiceException) e).getMessage());
            // 内部错误
//            log.error(String.format("[登录失败] - [%s]内部错误", username), e);
            result = RestResponse.fail(SecurityResponseCode.SECURITY_AUTHORIZATION_FAIL);

        } else {
            // 其他错误
            log.error(e.getMessage(), e);
//            log.error(String.format("[登录失败] - [%s]其他错误", username), e);
            result = RestResponse.fail(SecurityResponseCode.SECURITY_AUTHORIZATION_FAIL);
        }

        if (eventHook != null) {
            eventHook.loginFailureEvent(request, e);
        }
        // TODO 登录失败 记录日志
        // 允许跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        // 允许自定义请求头token(允许head跨域)
        response.setHeader("Access-Control-Allow-Headers",
                "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSON.toJSONString(result));
    }
}
